package com.abe.libcore.base.http

import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import com.abe.libcore.base.http.cookie.CookieManager
import com.abe.libcore.base.http.interceptor.HeaderInterceptor
import com.abe.libcore.base.http.interceptor.OKHttpInterceptor
import com.abe.libcore.utils.NetWorkUtils
import okhttp3.*
import java.security.SecureRandom
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

object OkHttpClientUtils {
    //连接时长，单位：毫秒
    private const val defaultConnectTimeOut: Long = 767600
    //读超时长，单位：毫秒
    private const val defaultReadTimeOut: Long = 767600
    //写超时长，单位：毫秒
    private const val defaultWriteTimeOut: Long = 767600

    //设缓存有效期为两天
    private const val CACHE_STALE_SEC: Long = 60 * 60 * 24 * 2

    fun initHttpClient(context: Context, vararg interceptors: Interceptor): OkHttpClient {
        // 创建OkHttpClient
        val builder = OkHttpClient.Builder()
        // 超时设置
        builder.connectTimeout(defaultConnectTimeOut, TimeUnit.SECONDS)
        builder.readTimeout(defaultReadTimeOut, TimeUnit.SECONDS)
        builder.writeTimeout(defaultWriteTimeOut, TimeUnit.SECONDS)
        // 错误重连
        builder.retryOnConnectionFailure(true)
        // 支持HTTPS
        builder.connectionSpecs(listOf(ConnectionSpec.CLEARTEXT, ConnectionSpec.MODERN_TLS))
        builder.addNetworkInterceptor(NetworkInterceptor(context))
        for (interceptor: Interceptor in interceptors) {
            builder.addInterceptor(interceptor)
        }
        builder.addInterceptor(OKHttpInterceptor())
        builder.addInterceptor(HeaderInterceptor())
        try {
            builder.sslSocketFactory(getSSLSocketFactory(), getTrustManager())
        } catch (e: Exception) {
            e.printStackTrace()
        }
        // cookie管理
        builder.cookieJar(CookieManager(context))
        return builder.build()
    }

    class NetworkInterceptor(var context: Context) : Interceptor {
        override fun intercept(chain: Interceptor.Chain?): Response {
            var request = chain!!.request()
            val cacheControl = request.cacheControl().toString()
            if (!isNetworkAvailable(context)) {
                request = request.newBuilder()
                        .cacheControl(if (TextUtils.isEmpty(cacheControl)) CacheControl.FORCE_NETWORK else CacheControl.FORCE_CACHE)
                        .build()
            }
            val originalResponse = chain.proceed(request)
            return if (isNetworkAvailable(context)) {
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
                originalResponse.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build()
            } else {
                originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=$CACHE_STALE_SEC")
                        .removeHeader("Pragma")
                        .build()
            }
        }
    }

    private fun getSSLSocketFactory(): SSLSocketFactory {
        val trustManager: Array<TrustManager> = Array(1) { getTrustManager() }
        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, trustManager, SecureRandom())
        return sslContext.socketFactory
    }

    @SuppressLint("TrustAllX509TrustManager")
    private fun getTrustManager(): X509TrustManager {
        return object : X509TrustManager {
            @Throws(java.security.cert.CertificateException::class)
            override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {

            }

            @Throws(java.security.cert.CertificateException::class)
            override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {

            }

            override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate?> {
                return arrayOfNulls(0)
            }
        }
    }

    /**
     * 判断网络是否可用
     */
    private fun isNetworkAvailable(context: Context): Boolean {
        return NetWorkUtils.getNetWorkState(context) != NetWorkUtils.NETWORK_NONE
    }
}